Skip to content

Fix Windows CI: Split interactions.cpp to avoid compiler heap exhaustion#13

Merged
0xeb merged 9 commits intomainfrom
fix/split-interactions-tests
Nov 29, 2025
Merged

Fix Windows CI: Split interactions.cpp to avoid compiler heap exhaustion#13
0xeb merged 9 commits intomainfrom
fix/split-interactions-tests

Conversation

@0xeb
Copy link
Copy Markdown
Owner

@0xeb 0xeb commented Nov 28, 2025

Summary

Fixes Windows CI compiler heap exhaustion (C1060) through a combination of file splitting and build parallelism reduction.

Problem

Windows CI failed with:

error C1060: compiler is out of heap space

Root causes:

  1. Massive test file: tests/server/interactions.cpp was 5,548 lines / 193KB
  2. Memory-constrained CI: GitHub's windows-latest runners have only 16GB RAM
  3. Parallel compilation: Default MSBuild settings spawned too many cl.exe processes, exhausting memory with template-heavy code

Solution (Multi-Phase)

Phase 1: Initial 3-way Split

Split original file into 3 parts (~1,800 lines each):

  • interactions_part1.cpp (55 tests)
  • interactions_part2.cpp (59 tests)
  • interactions_part3.cpp (50 tests)

Result: Part 2 still hit OutOfMemoryException at 2,105 lines

Phase 2: 4-way Split

Further split Part 2:

  • interactions_part1.cpp (55 tests, 1,990 lines)
  • interactions_part2a.cpp (30 tests, 1,200 lines)
  • interactions_part2b.cpp (29 tests, 1,049 lines)
  • interactions_part3.cpp (50 tests, 1,742 lines)

Result: Part 2a STILL hit C1060 at 1,200 lines (deeply nested JSON initializers)

Phase 3: Reduce Build Parallelism ✅

Modified .github/workflows/ci.yml:

- name: Configure (Windows)
  run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64  # Ensure 64-bit

- name: Build (Windows)
  run: cmake --build build --config ${{ matrix.build_type }} -- /m:4 /p:CL_MPCount=1
  # /m:4 limits MSBuild to 4 workers
  # /p:CL_MPCount=1 disables cl.exe's /MP flag

This reduces peak compiler memory usage while maintaining reasonable build performance.

Test Results

Local (Windows):

4/4 Test #28-31: fastmcpp_server_interactions_part* ...   Passed    0.07 sec

All 164 tests accounted for ✓

Changes

  • Split tests/server/interactions.cpp → 4 separate files
  • Updated CMakeLists.txt for 4 test targets
  • Modified .github/workflows/ci.yml to reduce Windows build parallelism
  • Test count: 37 → 40 (net +3 from split)

Related

References

0xeb added 2 commits November 28, 2025 11:32
Remove problematic connection test that was causing macOS CI failures:
- Removed immediate-cancel connection check (lines 51-67)
- Increased server startup wait from 1s to 2s for macOS
- Added 100ms delay before SSE thread connection attempts

The test connection was canceling immediately (line 61 returned false)
which caused connection handling errors on macOS that persisted into
the actual test. This left the server in a bad state for subsequent
POST and SSE connections.

Fixes: #<issue>
Split tests/server/interactions.cpp (5,548 lines, 193KB) into 3 smaller
files to avoid MSVC C1060 "compiler is out of heap space" error on GitHub
Actions Windows CI.

Issue: Windows CI failed at interactions.cpp:2307 with C1060 during both
Debug and Release builds. The file was too large for MSVC to compile in
CI's constrained environment, despite compiling fine locally with the same
compiler version (MSVC 14.44.35207).

Solution: Split into 3 parts following the same pattern as commit 54dc027
which explicitly "split large test files for maintainability":

- interactions_part1.cpp (55 tests, 1,989 lines) - Core Tools/Resources/Prompts
- interactions_part2.cpp (59 tests, 2,104 lines) - Data types/Validation
- interactions_part3.cpp (50 tests, 1,741 lines) - Server capabilities/Notifications

All 164 tests accounted for and passing locally (3/3 tests, 0.04s).

Related: PR #11 (43e5e64) which introduced the large interactions.cpp file.
This change maintains all test coverage while fixing Windows CI builds.
0xeb added a commit that referenced this pull request Nov 29, 2025
Fixes macOS CI test failures in fastmcpp_sse_server test.

Issue: Connection readiness check immediately canceled connections, leaving server in bad state on macOS.

Solution:
- Removed flaky connection test (lines 51-67, -20 lines)
- Increased server startup wait (1s → 2s for macOS compatibility)
- Added 100ms delay before SSE thread connection

Result: macOS Debug/Release tests now passing ✅

Note: Windows failures are pre-existing heap exhaustion issue (C1060), addressed separately in PR #13.
0xeb added 7 commits November 28, 2025 16:46
After initial 3-way split, Windows CI still failed with OutOfMemoryException
on interactions_part2.cpp (2,105 lines). MSBuild's tracking system ran out
of memory during compilation.

Solution: Split part2 into part2a and part2b (~1,050 lines each):

- interactions_part1.cpp  (55 tests, 1,990 lines)
- interactions_part2a.cpp (30 tests, 1,200 lines) - NEW
- interactions_part2b.cpp (29 tests, 1,049 lines) - NEW
- interactions_part3.cpp  (50 tests, 1,742 lines)

Total: 164 tests across 4 files (was 3 files).

Windows CI error was:
  System.OutOfMemoryException in MSBuild TrackedVCToolTask
  File: fastmcpp_server_interactions_part2.vcxproj

All 4 parts now compile and pass locally (4/4 tests, 0.07s).

Max file size now ~2,000 lines vs original 5,548 lines.
Windows CI was hitting C1060 "compiler is out of heap space" even after
splitting test files to 1,200 lines. Root cause: GitHub's windows-latest
runners have only 16GB RAM, and parallel cl.exe processes exhaust memory
with template-heavy code.

Solution (based on Microsoft docs + community solutions):
1. Add `-A x64` to ensure 64-bit toolset (32-bit has ~2-3GB limit)
2. Use `/m:4` to limit MSBuild to 4 worker processes
3. Use `/p:CL_MPCount=1` to disable cl.exe's internal /MP flag

This reduces peak compiler memory usage while still maintaining reasonable
build performance (~4x parallelism at MSBuild level).

Refs:
- https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1060
- appveyor/ci#742
The previous commit added -A x64 flag, but GitHub Actions cache
had a build directory configured without it. CMake errors when the
generator platform changes.

Fix: Delete CMakeCache.txt before configuring to allow clean
reconfiguration with the new x64 platform flag.
Previous attempt only removed CMakeCache.txt, but CMake also caches
configuration in the CMakeFiles directory. Both need to be removed
when changing generator platform flags.
The cached build/_deps contains FetchContent dependencies compiled
without -A x64 flag. Adding x64 to cache key forces fresh build of
dependencies with correct platform configuration.
Deeply nested JSON initializers in test files (9+ levels) cause MSVC
to exhaust compiler heap even with /m:4. Switching to /m:1 for maximum
memory conservation on GitHub's 16GB Windows runners.
The 9-level nested JSON initializer at line 549 exhausts MSVC compiler
heap even with single-threaded builds on GitHub's 16GB Windows runners.

Solution: Build the nested schema programmatically instead of using
nested initializers. This significantly reduces compiler memory pressure
while producing identical runtime results.

Tested locally: All 30 Part 2a tests pass.
@0xeb 0xeb merged commit b2b2772 into main Nov 29, 2025
9 checks passed
@0xeb 0xeb deleted the fix/split-interactions-tests branch November 29, 2025 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant